#pragma once
#ifndef LIT__EDITOR__LEXER__HH__
#define LIT__EDITOR__LEXER__HH__

#include <string>
#include <list>

#include <LitEditorPrerequisites.h>
#include <LitEditorPolice.h>

namespace Lit
{
	namespace Editor
	{
		namespace Lexer
		{
			struct LIT_API Word
			{
				std::string letters;
				Word( );
				Word( const std::string &w );
				Word( const Word &rk );
			
				bool operator==( const Word& rk ) const;
				bool operator!=( const Word& rk ) const;
				bool operator<( const Word& rk ) const;

				size_t length() const;
				bool empty() const;
				Word& operator = ( const Word &rk );
				operator std::string() const;
			};
			struct LIT_API WordGroup : public std::list<Word>
			{
				Police police;

				WordGroup( const Police &polc = Police() );
				WordGroup( const WordGroup &w );
				WordGroup( const std::list<Word> &w ) ;
				~WordGroup();
			
				WordGroup& merge( const WordGroup& rk )
				{
					for( auto i=rk.begin();i!=rk.end();i++ )
						push_back( (*i) );
					return *this;
				}
				void push_back( const Word& w );
				void push_front( const Word& w );

				void push_back( const std::string& w );
				void push_front( const std::string& w );

				WordGroup& operator << ( const Word& w );
				WordGroup& operator()( const Word& w );
				WordGroup& operator+=( const Word& w );

				WordGroup& operator << ( const std::string& w );
				WordGroup& operator()( const std::string& w );
				WordGroup& operator+=( const std::string& w );

				WordGroup& operator=( const WordGroup& w );

				iterator find( const Word& rk );
				const_iterator find( const Word& rk ) const;
			};
			typedef std::unordered_map<std::string, WordGroup> WordGroupMap;
			class LIT_API Keywords
			{
			public:
				struct HighlightingRule
				{
					HighlightingRule(  )
					{}
					HighlightingRule( const HighlightingRule &rk )
						: pattern( rk.pattern ), format(rk.format)
					{}
					HighlightingRule( const QRegExp& pattern_, const Police& format_ )
						: pattern( pattern_ ), format(format_)
					{}

					QRegExp pattern;
					Police format;
				};
				typedef std::vector<HighlightingRule> HighlightingRuleList;
			
			protected:
				WordGroupMap mGroups;
			public:
				Keywords( ){}
				Keywords( const Keywords& rk ) : mGroups(rk.mGroups){}
				virtual ~Keywords(){}
			
				virtual HighlightingRuleList getHighlightingRules() = 0;
			
				WordGroup* addGroup( const std::string &name, const WordGroup& g )
				{ 
					if( !hasGroup( name ) ) 
						mGroups[name] = g; 
					else mGroups[name].merge( g );
					return &mGroups.at(name);
				}
				WordGroup* getGroup( const std::string &name )
				{ 
					if( !hasGroup( name ) ) return NULL;
					return &mGroups.at(name);
				}
				const WordGroup* getGroup( const std::string &name ) const
				{ 
					if( !hasGroup( name ) ) return NULL;
					return &mGroups.at(name);
				}
				bool hasGroup( const std::string &name ) const
				{
					return mGroups.find(name) != mGroups.end();
				}
				void removeGroup( const std::string &name )
				{
					if( !hasGroup(name) ) return;
					mGroups.erase( mGroups.find(name) );
				}
			};
			class LIT_API MaterialKeywords : public Keywords
			{
				HighlightingRuleList mRules;
			public:
				static QRegExp commentStartExpression;
				static QRegExp commentEndExpression;

				static HighlightingRule classFormat;
				static HighlightingRule singleLineCommentFormat;
				static HighlightingRule multiLineCommentFormat;
				static HighlightingRule quotationFormat;
				static HighlightingRule functionFormat;

				MaterialKeywords();
				~MaterialKeywords();

				HighlightingRuleList getHighlightingRules();
			
				WordGroup Group0;
				WordGroup Group1;
				WordGroup Group2;
				WordGroup Group3;
			};
		};
	};
};

#endif